package com.googlecode.skald.server.demo;

/**
 * An object in the world that can be interacted with.
 * 
 * @author Zach Tomaszewski
 */
public abstract class WorldObject {

  private WorldObject loc;

  /** 
   * Returns whether this object currently affords having the given 
   * action performed on it.  That is, does it appear that this object
   * could currently serve as the direct object of the given action, 
   * which must have an arity >= 1.
   * <p>
   * By default, the object cannot; override to specify behavior.
   */
  public Afforded affordsDobj(Action act) {
    return Afforded.NOT;
  }
  
  /** 
   * Returns whether this object currently affords having the given 
   * action performed with it.  That is, does it appear that this object
   * could currently serve as the indirect object of the given action, 
   * which must have an arity >= 1.
   * <p>
   * By default, the object cannot; override to specify behavior.
   */
  public Afforded affordsIobj(Action act) {
    return Afforded.NOT;
  }

  /**
   * Performs the given action as actor.  In general, this is just a test
   * that the following action is currently permissible.  Depending on the
   * action's arity, dobj and iobj may be null. 
   * <p> 
   * Returns any narration of the event (which may be an empty string) or 
   * throws an ActionAbortedException to prevent the action.
   */
  public String actorOf(Action act, WorldObject dobj, WorldObject iobj) 
        throws ActionAbortedException {
    return "";
  }

  /**
   * Performs the given action as the direct object or recipient of the action.
   * That is, dobj == this.
   * <p>
   * This is generally where most action effects should occur, since most 
   * actions affect the direct object most strongly (if there is one).  
   * If there is an iobj, {@link #iobjOf(Action, WorldObject, WorldObject)}
   * should have already been called on that iobj. 
   * <p>
   * Returns any narration of the event (which may be an empty string) 
   * or throws an ActionAbortedException.  In general
   */
  public String dobjOf(Action act, WorldObject dobj, WorldObject iobj)  
        throws ActionAbortedException {
    return "";
  }

  /**
   * Performs the given action as indirect object. That is, this == iobj. 
   * <p>
   * In general, this is just a test that the following action is currently 
   * permissible.  
   * <p> 
   * Returns any narration of the event (which may be an empty string) or 
   * throws an ActionAbortedException to prevent the action.
   */
  public String iobjOf(Action act, WorldObject dobj, WorldObject iobj)  
        throws ActionAbortedException {
    return "";
  }
  
  /**
   * Returns the simple name of this object.
   */
  public String getName() {
    return this.getClass().getSimpleName().toLowerCase();
  }
  
  /**
   * Same as {@link #getParent()}.
   */
  public WorldObject getLocation() {
    return loc;
  }  
  
  /**
   * Returns this objects current container.  If not in anything right now,
   * returns null. 
   */
  public WorldObject getParent() {
    return loc;
  }
  
  /**
   * Moves this object into the given container.  Pass null to move out into
   * the world at large.
   */
  public void moveTo(WorldObject loc) {
    this.loc = loc;
  }
  
  /** 
   * As {@link #toString(String)} with this object's name as the 
   * description.
   */
  @Override
  public String toString() {
    return this.toString(this.getName()); 
  }
  
  /**
   * Returns the given description of this object wrapped in an
   * appropriate Skald &lt;a href&gt;...&lt;/a&gt; tag. 
   */
  public String toString(String desc) {
    return "<a href=\"?" + this.getName() + "\">" + desc + "</a>";
  }
}
